package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	
	"ebbflow/pkg/cbr"
	"ebbflow/src/consensus"
)

func main() {
	// Parse command line arguments
	nodeID := flag.Int("id", 0, "Node ID")
	totalNodes := flag.Int("n", 4, "Total number of nodes")
	faultyNodes := flag.Int("f", 1, "Number of faulty nodes")
	epochs := flag.Int("epochs", 10, "Number of epochs to run")
	reconfigInterval := flag.Int("r", 5, "Reconfiguration interval (execute CBR every R epochs)")
	
	flag.Parse()
	
	// Setup logger
	logger := log.New(os.Stdout, fmt.Sprintf("[Node %d] ", *nodeID), log.LstdFlags)
	
	logger.Printf("Starting EbbFlow CBR Demo")
	logger.Printf("Configuration: N=%d, F=%d, Epochs=%d, R=%d", *totalNodes, *faultyNodes, *epochs, *reconfigInterval)
	
	// Create CBR instance
	cbrNode := consensus.NewEbbFlowCBR(*nodeID, *totalNodes, *faultyNodes, logger)
	
	// Run CBR for multiple epochs
	for epoch := 0; epoch < *epochs; epoch++ {
		logger.Printf("=== Epoch %d ===", epoch)
		
		// Check if CBR should execute at this epoch
		if cbrNode.ShouldExecute(epoch) {
			logger.Printf("Executing CBR reconfiguration for epoch %d", epoch)
			
			// Generate new membership (in real scenario, this would come from consensus)
			newMembership := generateMembership(*totalNodes)
			
			result, err := cbrNode.ExecuteReconfiguration(epoch, newMembership)
			if err != nil {
				logger.Printf("CBR execution failed: %v", err)
				continue
			}
			
			logger.Printf("CBR completed successfully in %v", result.Duration)
			logger.Printf("New membership: %v", result.NewMembership)
		} else {
			logger.Printf("Skipping CBR (not a reconfiguration epoch)")
		}
	}
	
	// Print final metrics
	metrics := cbrNode.GetMetrics()
	logger.Printf("\n=== CBR Performance Metrics ===")
	logger.Printf("Total Executions: %d", metrics.TotalExecutions)
	logger.Printf("Successful: %d", metrics.SuccessfulExecutions)
	logger.Printf("Failed: %d", metrics.FailedExecutions)
	logger.Printf("Average Duration: %v", metrics.AverageDuration)
	
	logger.Printf("CBR Demo completed successfully")
}

func generateMembership(totalNodes int) []string {
	membership := make([]string, totalNodes)
	for i := 0; i < totalNodes; i++ {
		membership[i] = fmt.Sprintf("127.0.0.1:%d", 8000+i)
	}
	return membership
}

